NPCCTF 2025 ezMobile

简单dex壳

进来主类里直接看到一个经典dex壳,这个壳是吧加密过的dex扔进native函数里解密,然后用InMemoryDexClassLoader动态加载

我们直接hook这个change,拿到返回值后直接写进入文件获得dex

1
2
3
4
5
6
7
8
9
10
def onMessage(message, data):
if message['type'] == 'send':
print("[!!] Message from target: ", message['payload'])
for i in range(len(message['payload'])):
if message['payload'][i] < 0:
message['payload'][i] += 256
with open("class.dex", "wb") as f:
f.write(bytes(message['payload']))
else:
print("Not a send type Message", message['stack'])
1
2
3
4
5
6
let MainActivity = Java.use("ctf.myapplication.MainActivity");
MainActivity["change"].implementation = function (bArr) {
let result = this["change"](bArr);
send(result)
return result;
};

拿到dex后打开看加密


就是一个xxtea加一个base64,base64检查过后发现就是默认表,xxtea魔改了MX和delta,所以手动写xxtea脚本,key是放在native里的,可以直接hook encrypt的参数获取

1
FlagChecker.encrypt is called: data=qweery, key=882059e204adefc5

xxtea脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <bits/stdc++.h>
using namespace std;
#define MX (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p & 3) ^ e] ^ z))
void xxteaEncrtpy(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = -1640531527;
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += delta;
e = (sum >> 2) & 3; // 引入非线性计算,使得每次取出的key值缺少规律
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX; // 每个块加密是增加的偏移量实际上由上一个块(z)和下一个块(y)的值和sum共同决定
}
y = v[0]; // 此处其实是循环加密的端点,当然可以对下标取模写进循环里
z = v[n - 1] += MX;
} while (--rounds); // 实际上是把相同的操作重复round轮
}
void xxteaDecrypt(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = -1640531527;
rounds = 6 + 52 / n;
sum = rounds * delta;
y = v[0]; // n-1号块的下一个块是0号块
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) // 反向循环
{
z = v[p - 1]; // 因为是反着循环,所以这里是上一个块
y = v[p] -= MX; // 这里是也是取上一个和下一个块的值作为参数
}
z = v[n - 1]; // 0号块的上一个块是n-1号块
y = v[0] -= MX;
sum -= delta;
} while (--rounds);
}
int main()
{ // 882059e204adefc5
char k[] = "882059e204adefc5";
// uint32_t k[4] = {0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210};
unsigned char v[] = {0x61,
0x80,
0x8a,
0x2d,
0x69,
0x52,
0x27,
0xdc,
0x78,
0x95,
0x85,
0x66,
0xee,
0x2a,
0xa5,
0x1e,
0xdf,
0xc4,
0x5e,
0xf8,
0x1a,
0x84,
0x4a,
0x0a,
0x11,
0xed,
0x9d,
0x97,
0x40,
0x67,
0x46,
0x61,
0xa1,
0x35,
0x0f,
0x4a,
0x84,
0xf5,
0xd8,
0x79,
0xfd,
0xc4,
0xa9,
0xb8};
xxteaDecrypt((uint32_t *)v, 11, (uint32_t *)k);
for (int i = 0; i < 44; i++)
printf("%c", v[i]);
printf("\n");
return 0;
}

flag{AnDr01d_r3v3rs3_jUcYuWzBSSOwKxbMD}

Author

SGSG

Posted on

2025-04-11

Updated on

2025-04-18

Licensed under